#!/usr/bin/env python3
import sys
import os
import subprocess
import fileinput
from argparse import ArgumentParser

def alias_conf_file():
    return os.path.join(os.environ['HOME'], '.adbw_dev')

def alias_get(alias):
    if not os.path.isfile(alias_conf_file()):
        return ''
    with fileinput.FileInput([alias_conf_file()]) as f:
        for line in f:
            if line.split()[0] == alias:
                return line.split()[1]
    return ''

def alias_set(alias, serial):
    tmp_file = alias_conf_file() + '.tmp'
    with open(tmp_file, 'w') as tf:
        try:
            with fileinput.FileInput([alias_conf_file()]) as f:
                for line in f:
                    if line.split()[0] != alias:
                        tf.write(line)
        except FileNotFoundError:
            pass
        tf.write('{} {}\n'.format(alias, serial))
    os.rename(tmp_file, alias_conf_file())

def alias_dev_of_alias(serial):
    if not os.path.isfile(alias_conf_file()):
        return ''
    with fileinput.FileInput([alias_conf_file()]) as f:
        for line in f:
            if line.split()[1] == serial:
                return line.split()[0]
    return ''

def get_devs():
    devs = []
    output = subprocess.check_output('adb devices', shell=True, universal_newlines=True)
    for line in output.splitlines():
        if not line or line.find('List of') != -1 or line.find('device') == -1:
            continue
        devs.append(line.split()[0])
    return devs

def get_dev_model(serial):
    cmd = ['adb', '-s', serial, 'shell', 'getprop', 'ro.product.model']
    return subprocess.check_output(cmd, universal_newlines=True).rstrip()

def peek_args():
    origin = sys.argv[:]
    if origin[0].find('python') == 0:
        origin.pop(0)
    origin.pop(0)
    return origin

def handle_alias(devs, alias_cmd):
    params = alias_cmd.split()
    try:
        dev_index = int(params[1])
    except:
        print('bad index of device to alias: ' + params[1])
        return
    alias_name = params[2]
    if dev_index >=0 and dev_index < len(devs) :
        print('alias {} = [device serial: {}, model:{}] OK'.format(alias_name, devs[dev_index], get_dev_model(devs[dev_index])))
        alias_set(alias_name, devs[dev_index])
    else:
        print('index of device to alias not exist: ' + dev_index)

def select_dev(devs):
    print('attached devices: ')
    index = 0
    for dev in devs:
        print('[{}]  model: {}, serial: {}'.format(index, get_dev_model(dev), dev))
        index += 1
    select = input('input: [number] or [alias number alias_name]: ')
    while select.find('alias') == 0:
        handle_alias(devs, select)
        select = input('input: [number] or [alias number alias_name]: ')
    return devs[int(select)]

def is_list_cmd(adb_args):
    return len(adb_args) >=1 and adb_args[0] == 'devices'

def translate_alias_device_select(adb_args):
    if len(adb_args) < 2:
        return adb_args
    new_args = adb_args[:]
    if new_args[0] == '-S':
        new_args[0] = '-s'
        serial = alias_get(new_args[1])
        if serial != '':
            new_args[1] = serial        
    return new_args

def selected_device(adb_args):
    if len(adb_args) >= 2 and adb_args[0] == '-s':
        return adb_args[1]
    return ''

def handle_adb_devices(args):
    if is_list_cmd(args):
        devs = get_devs()
        print('List of devices attached\n')
        for dev in devs:
            print('{}(model: {}, alias: {})    device'.format(dev, get_dev_model(dev), alias_dev_of_alias(dev)))
        sys.exit(0)

origin_args = peek_args()
handle_adb_devices(origin_args)

origin_args = translate_alias_device_select(origin_args)

cmd = ['adb']

devs = get_devs()
if selected_device(origin_args) == '' and len(devs) > 1 and not is_list_cmd(origin_args):
    dev = select_dev(devs)
    cmd.append('-s')
    cmd.append(dev)

cmd.extend(origin_args)
print('cmd: ' + str(cmd))
subprocess.call(cmd)
